/*
 *  author: Honrun
 */
#include "stm32f4xx_hal.h"
#include "DevicesDelay.h"
#include "DevicesSoftIIC.h"


SoftIICHandle ex_SoftIICRT8092VCC2Handle;


void vSoftIICRT8092VCC2Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    SOFT_IIC_RT8092_VCC2_SCK_RCC_GPIO_CLK_ENABLE();
    SOFT_IIC_RT8092_VCC2_SDA_RCC_GPIO_CLK_ENABLE();

    /*Configure GPIO pin Output Level */
    HAL_GPIO_WritePin(SOFT_IIC_RT8092_VCC2_SCK_GPIO_Port, SOFT_IIC_RT8092_VCC2_SCK_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(SOFT_IIC_RT8092_VCC2_SDA_GPIO_Port, SOFT_IIC_RT8092_VCC2_SDA_Pin, GPIO_PIN_SET);

    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pin = SOFT_IIC_RT8092_VCC2_SCK_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(SOFT_IIC_RT8092_VCC2_SCK_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pin = SOFT_IIC_RT8092_VCC2_SDA_Pin;
    HAL_GPIO_Init(SOFT_IIC_RT8092_VCC2_SDA_GPIO_Port, &GPIO_InitStruct);


    ex_SoftIICRT8092VCC2Handle.SclGPIO = SOFT_IIC_RT8092_VCC2_SCK_GPIO_Port;
    ex_SoftIICRT8092VCC2Handle.SclPin = SOFT_IIC_RT8092_VCC2_SCK_Pin;

    ex_SoftIICRT8092VCC2Handle.SdaGPIO = SOFT_IIC_RT8092_VCC2_SDA_GPIO_Port;
    ex_SoftIICRT8092VCC2Handle.SdaPin = SOFT_IIC_RT8092_VCC2_SDA_Pin;

    ex_SoftIICRT8092VCC2Handle.GPIOSetMode = vSoftIICxSetSdaGPIOMode;
    ex_SoftIICRT8092VCC2Handle.GPIOSetHigh = HAL_GPIO_WritePin;
    ex_SoftIICRT8092VCC2Handle.GPIOSetLow = HAL_GPIO_WritePin;
    ex_SoftIICRT8092VCC2Handle.GPIOReadBit = HAL_GPIO_ReadPin;

    ex_SoftIICRT8092VCC2Handle.delayTime = SOFT_IIC_RT8092_VCC2_DELAY_BIT_TIME;
}

void vSoftIICxSetSdaGPIOMode(struct SoftIICStruct *pHandle, uint32_t typeMode)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /*Configure GPIO pin : PtPin */
    GPIO_InitStruct.Mode = typeMode;
    GPIO_InitStruct.Pin = pHandle->SdaPin;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(pHandle->SdaGPIO, &GPIO_InitStruct);
}

void vSoftIICxStart(SoftIICHandle *pHandle)
{
    pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetLow(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_RESET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetLow(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_RESET);
    vDelayUs(pHandle->delayTime);
}

void vSoftIICxStop(SoftIICHandle *pHandle)
{
    pHandle->GPIOSetLow(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_RESET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);
}

void vSoftIICxWriteACKState(SoftIICHandle *pHandle, uint8_t ucACKState)
{
    if(ucACKState == SORT_IIC_NACK)
        pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);
    else
        pHandle->GPIOSetLow(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_RESET);

    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetLow(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_RESET);
    vDelayUs(pHandle->delayTime);
}

uint8_t ucSoftIICxReadACKState(SoftIICHandle *pHandle)
{
    uint8_t ucACKState = SORT_IIC_NACK;

//    pHandle->GPIOSetMode(pHandle, GPIO_MODE_INPUT);

    pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
    vDelayUs(pHandle->delayTime);

    if(pHandle->GPIOReadBit(pHandle->SdaGPIO, pHandle->SdaPin) == 0)
        ucACKState = SORT_IIC_ACK;

    pHandle->GPIOSetLow(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_RESET);
    vDelayUs(pHandle->delayTime);

//    pHandle->GPIOSetMode(pHandle, GPIO_MODE_OUTPUT_PP);

    return ucACKState;
}

void vSoftIICxWriteByte(SoftIICHandle *pHandle, uint8_t ucData)
{
    uint8_t ucMask = 0x80;

    for(ucMask = 0x80; ucMask; ucMask >>= 1)
    {
        if(ucData & ucMask)
            pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);
        else
            pHandle->GPIOSetLow(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_RESET);

        vDelayUs(pHandle->delayTime);

        pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
        vDelayUs(pHandle->delayTime);

        pHandle->GPIOSetLow(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_RESET);
        vDelayUs(pHandle->delayTime);
    }
}

uint8_t ucSoftIICxReadByte(SoftIICHandle *pHandle)
{
    uint8_t ucMask = 0x80, ucData = 0x00;

//    pHandle->GPIOSetMode(pHandle, GPIO_MODE_INPUT);
    pHandle->GPIOSetHigh(pHandle->SdaGPIO, pHandle->SdaPin, GPIO_PIN_SET);

    for(ucMask = 0x80; ucMask; ucMask >>= 1)
    {
        pHandle->GPIOSetHigh(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_SET);
        vDelayUs(pHandle->delayTime);

        if(pHandle->GPIOReadBit(pHandle->SdaGPIO, pHandle->SdaPin) != 0)
            ucData |= ucMask;

        pHandle->GPIOSetLow(pHandle->SclGPIO, pHandle->SclPin, GPIO_PIN_RESET);
        vDelayUs(pHandle->delayTime);
    }

//    pHandle->GPIOSetMode(pHandle, GPIO_MODE_OUTPUT_PP);

    return ucData;
}

int8_t cSoftIICxWriteDatas(SoftIICHandle *pHandle, uint8_t ucAddr, uint8_t ucReg, uint8_t *pucDatas, uint32_t iLength)
{
    int32_t i = 0;
    int8_t cError = 0x01;

    /* 重复给予起始信号 */
    for(i = 0; i < 8; ++i)
    {
        vSoftIICxStart(pHandle);

        vSoftIICxWriteByte(pHandle, ucAddr | SORT_IIC_WRITE_MODE);
        if(ucSoftIICxReadACKState(pHandle) == SORT_IIC_ACK)
        {
            cError = 0x00;
            break;
        }
        else
            vDelayUs(100);
    }

    vSoftIICxWriteByte(pHandle, ucReg);
    if(ucSoftIICxReadACKState(pHandle) != SORT_IIC_ACK)
        cError |= 0x02;

    for(i = 0; i < iLength; ++i)
    {
        vSoftIICxWriteByte(pHandle, *pucDatas++);
        if(ucSoftIICxReadACKState(pHandle) != SORT_IIC_ACK)
            cError |= 0x04;
    }

    vSoftIICxStop(pHandle);

    return cError;
}

int8_t cSoftIICxWriteByte(SoftIICHandle *pHandle, uint8_t ucAddr, uint8_t ucReg, uint8_t ucByte)
{
    return cSoftIICxWriteDatas(pHandle, ucAddr, ucReg, &ucByte, 1);
}

int8_t cSoftIICxReadDatas(SoftIICHandle *pHandle, uint8_t ucAddr, uint8_t ucReg, uint8_t *pucDatas, int32_t iLength)
{
    int32_t i = 0;
    int8_t cError = 0x01;

    /* 重复给予起始信号 */
    for(i = 0; i < 8; ++i)
    {
        vSoftIICxStart(pHandle);

        vSoftIICxWriteByte(pHandle, ucAddr | SORT_IIC_WRITE_MODE);
        if(ucSoftIICxReadACKState(pHandle) == SORT_IIC_ACK)
        {
            cError = 0x00;
            break;
        }
        else
            vDelayUs(100);
    }

    vSoftIICxWriteByte(pHandle, ucReg);
    if(ucSoftIICxReadACKState(pHandle) != SORT_IIC_ACK)
        cError |= 0x02;

    vSoftIICxStart(pHandle);

    vSoftIICxWriteByte(pHandle, ucAddr | SORT_IIC_READ_MODE);
    if(ucSoftIICxReadACKState(pHandle) != SORT_IIC_ACK)
        cError |= 0x04;

    iLength -= 1;
    for(i = 0; i < iLength; ++i)
    {
        *pucDatas++ = ucSoftIICxReadByte(pHandle);
        vSoftIICxWriteACKState(pHandle, SORT_IIC_ACK);
    }

    *pucDatas = ucSoftIICxReadByte(pHandle);
    vSoftIICxWriteACKState(pHandle, SORT_IIC_NACK);

    vSoftIICxStop(pHandle);

    return cError;
}

int8_t cSoftIICxReadByte(SoftIICHandle *pHandle, uint8_t ucAddr, uint8_t ucReg, uint8_t *pucByte)
{
    return cSoftIICxReadDatas(pHandle, ucAddr, ucReg, pucByte, 1);
}
